package com.ocom.exposeapi.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.ocom.common.constant.ExposeApiUrl;
import com.ocom.common.dto.CompanyDockListDto;
import com.ocom.common.entity.card.EntityCardInfo;
import com.ocom.common.entity.card.EntityXfAccountInfo;
import com.ocom.common.entity.card.EntityXfRecordProcess;
import com.ocom.common.entity.company.EntityComDockApi;
import com.ocom.common.enums.ResultEnum;
import com.ocom.common.request.company.GetDockApiUrlRequest;
import com.ocom.common.request.company.GetReplyApiParaRequest;
import com.ocom.common.request.exposeapi.abc.ABCConfirmTraceRequest;
import com.ocom.common.resp.Result;
import com.ocom.common.utils.DateUtils;
import com.ocom.common.utils.F2YAndY2FUtils;
import com.ocom.common.utils.ResultUtil;
import com.ocom.common.utils.abc.Base64Util;
import com.ocom.common.utils.abc.DateUtil;
import com.ocom.common.utils.abc.HttpClientUtils;
import com.ocom.common.utils.abc.dto.*;
import com.ocom.common.vo.company.CompanyDockListVo;
import com.ocom.common.vo.company.DockApiUrlVo;
import com.ocom.common.vo.human.UserInfoByNamePhoneVo;
import com.ocom.common.vo.pay.ABCChargeConfirmVo;
import com.ocom.exposeapi.feign.CompanyClientService;
import com.ocom.exposeapi.feign.HumanFeignService;
import com.ocom.exposeapi.feign.PayConfigClientService;
import com.ocom.exposeapi.feign.PayHandleClientService;
import com.ocom.exposeapi.util.SignatureAndVerification;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;


@Slf4j
@RestController
public class ABCBridgeController {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private CompanyClientService companyClientService;

    @Autowired
    private HumanFeignService humanFeignService;

    @Autowired
    private PayConfigClientService payConfigClientService;

    @Autowired
    private PayHandleClientService payHandleClientService;

    @Autowired
    private SignatureAndVerification signatureAndVerification;


    @PostMapping(ExposeApiUrl.URL_ExposeApi_ABCBridgeQueryBill)
    public void queryBill(HttpServletRequest request, HttpServletResponse httpResponse) throws IOException {
//        logger.info("进入QueryBill账单查询接口========(金额规则为3的)========");
        String responseJson = null;
        //接收报文request返回截取并返回requsetBody和使用base64解析后的requsetBody
        Map<String, String> requestMap = signatureAndVerification.requestBodyOfBase64(request);
        //使用base64解析完成后的requsetBody
        String requsetBodyOfDecoded = requestMap.get("requsetBodyOfDecoded");
        //解析前的requsetBody
        String requsetBody = requestMap.get("requsetBody");
        //获取缴费中心传送过来的签名
        String signatureString = requestMap.get("signatureString");
        QueryBillRequest queryBillRequest = JSON.parseObject(requsetBodyOfDecoded, new TypeReference<QueryBillRequest>() {
        });

        logger.info("QueryBill账单查询接口查询参数：================" + queryBillRequest.toString());

        //返回给缴费中心的响应
        QueryBillResponse response = new QueryBillResponse(queryBillRequest);
        QueryBillResponse.Message respMessage = response.getMessage();
        QueryBillResponse.Message.Head respHead = response.getMessage().getHead();
        QueryBillResponse.Message.Info respInfo = response.getMessage().getInfo();

        ArrayList<QueryBillResponse.Message.Info.Bill> respBills = new ArrayList<QueryBillResponse.Message.Info.Bill>();
        ArrayList<QueryBillResponse.Message.Info.Bill.DescDetail> respDescDetail = new ArrayList<QueryBillResponse.Message.Info.Bill.DescDetail>();
        QueryBillResponse.Message.Info.Bill respBill = respInfo.new Bill();

        //返回代码
        String returnCode = "0000";
        String returnMessage = "账单查询成功";

        //私钥
        String privateKeyString = "";

        //返回代码
        ABCReturnDto returnDto = new ABCReturnDto("0000", "账单查询成功", "false");
        try {
//            logger.info("======================获取农行公钥");
            //获取农行公钥
            EntityComDockApi entityComDockApi = getReplyApiPara(queryBillRequest.getMessage().getInfo().getMerchantId(), "abcbridge#queryBill", 1, returnDto);
//            logger.info("======================获取私钥");
            //获取私钥
            EntityComDockApi entityComDockApi2 = getReplyApiPara(queryBillRequest.getMessage().getInfo().getMerchantId(), "abcbridge#queryBill", 4, returnDto);
            privateKeyString = entityComDockApi2.getKey();

//            logger.info("======================验签");
            // 验签
            verifySign(entityComDockApi.getKey(), requsetBody, signatureString, entityComDockApi.getComId(), queryBillRequest.getMessage().getInfo().getInput1(), returnDto);

            //业务
//            logger.info("======================调用部门人事微服务2.2.21根据姓名手机号获取人员信息getPinfoByNamePhone");
            //2、调用部门人事微服务2.2.21根据姓名手机号获取人员信息getPinfoByNamePhone
            UserInfoByNamePhoneVo entityPersonnelInfo = getPinfoByNameCode(entityComDockApi.getComId(), queryBillRequest.getMessage().getInfo().getInput3(), queryBillRequest.getMessage().getInfo().getInput2(), returnDto);

//            logger.info("======================调用消费配置微服务4.1获取账号信息getXFAccount");
            //3、调用消费配置微服务4.1获取账号信息getXFAccount
            EntityXfAccountInfo entityXfAccountInfo = getXFAccount(entityComDockApi.getComId(), Integer.valueOf(entityPersonnelInfo.getPId().toString()), returnDto);

            if(entityXfAccountInfo==null || entityXfAccountInfo.getAccountState()!=0){
                returnDto.setReturnCode("JH06");
                returnDto.setReturnMessage("学生账户不存在");
                returnDto.setRefundFlag("true");
                throw new Exception(returnDto.getReturnMessage());
            }


//            logger.info("======================调用消费操作微服务2.4.6 abcCharge往待处理表插入数据record");
            //4、调用消费操作微服务2.4.6 abcCharge往待处理表插入数据record，下图为对应的入库参数
            EntityXfRecordProcess entityXfRecordProcess = abcCharge(entityComDockApi, entityPersonnelInfo, entityXfAccountInfo, queryBillRequest.getMessage().getInfo().getTraceNo(), returnDto);

//            logger.info("======================账单查询成功3");
            setRespBills(respBill, respBills, entityXfRecordProcess.getOrderNo(), entityXfAccountInfo.getAccountRechargeMoney());

            setRespInfo(queryBillRequest, respInfo, entityPersonnelInfo.getPName(), entityPersonnelInfo.getDeptName(), respBills);

            setMessage(respHead, respInfo, respMessage, response, returnDto);

            responseJson = JSON.toJSONString(response);

        } catch (Exception e) {
//            logger.info("======================账单查询失败3");
            e.printStackTrace();
            setRespBills(respBill, respBills, "", 0l);

            setRespInfo(queryBillRequest, respInfo, "", "", respBills);

            setMessage(respHead, respInfo, respMessage, response, returnDto);

            responseJson = JSON.toJSONString(response);
        } finally {
            // 加签名
            logger.info("responseJson打印结果是（responseJson加密前）:" + responseJson);
            String signatrue = signatureAndVerification.signWhithsha1withrsa2(privateKeyString, responseJson);
//            logger.info("signatrue:" + signatrue);
            responseJson = signatrue + "||" + new String(Base64.encodeBase64(responseJson.getBytes("utf-8")));
//            logger.info("responseJson打印结果是（responseJson加密后）:" + responseJson);
            httpResponse.setCharacterEncoding("utf-8");
            httpResponse.setContentType("text/plain");
            httpResponse.getWriter().write(responseJson);
        }
    }


    @PostMapping(ExposeApiUrl.URL_ExposeApi_ABCBridgeChargeBill)
    public void chargeBill(HttpServletRequest request, HttpServletResponse httpResponse) throws IOException {

//        logger.info("========进入chargeBill==================================");
        String responseJson = null;
        //接收报文request返回截取并返回requsetBody和使用base64解析后的requsetBody
        Map<String, String> requestMap = signatureAndVerification.requestBodyOfBase64(request);
        //使用base64解析完成后的requsetBody
        String requsetBodyOfDecoded = requestMap.get("requsetBodyOfDecoded");
        //解析前的requsetBody
        String requsetBody = requestMap.get("requsetBody");
        //获取缴费中心传送过来的签名
        String signatureString = requestMap.get("signatureString");

        ChargeBillRequest chargeBillRequest = JSON.parseObject(requsetBodyOfDecoded, new TypeReference<ChargeBillRequest>() {
        });

        logger.info("chargeBill接口查询参数：================" + chargeBillRequest.toString());


        ChargeBillRequest.Message requestMessage = chargeBillRequest.getMessage();

        ChargeBillResponse chargeBillResponse = new ChargeBillResponse(chargeBillRequest);
        ChargeBillResponse.Message respMessage = chargeBillResponse.getMessage();
        ChargeBillResponse.Message.Head respHead = chargeBillResponse.getMessage().getHead();
        ChargeBillResponse.Message.Info respInfo = chargeBillResponse.getMessage().getInfo();

        //返回代码
        ABCReturnDto returnDto = new ABCReturnDto("0000", "账单缴费成功", "false");

        //私钥
        String privateKeyString = "";

        try {
//            logger.info("======================获取农行公钥");
            //获取农行公钥
            EntityComDockApi entityComDockApi = getReplyApiPara(requestMessage.getInfo().getMerchantId(), "abcbridge#chargeBill", 1, returnDto);

//            logger.info("======================获取私钥");
            //获取私钥
            EntityComDockApi entityComDockApi2 = getReplyApiPara(requestMessage.getInfo().getMerchantId(), "abcbridge#chargeBill", 4, returnDto);
            privateKeyString = entityComDockApi2.getKey();

//            logger.info("======================验签");
            // 验签
            verifySign(entityComDockApi.getKey(), requsetBody, signatureString, entityComDockApi.getComId(), requestMessage.getInfo().getInput1(), returnDto);

            //业务
//            logger.info("======================调用部门人事微服务2.2.21根据姓名手机号获取人员信息getPinfoByNamePhone");
            //2、调用部门人事微服务2.2.21根据姓名手机号获取人员信息getPinfoByNamePhone
            UserInfoByNamePhoneVo entityPersonnelInfo = getPinfoByNameCode(entityComDockApi.getComId(), requestMessage.getInfo().getInput3(), requestMessage.getInfo().getInput2(), returnDto);

//            logger.info("======================调用消费配置微服务4.1获取账号信息getXFAccount");
            //3、调用消费配置微服务4.1获取账号信息getXFAccount
            EntityXfAccountInfo entityXfAccountInfo = getXFAccount(entityComDockApi.getComId(), Integer.valueOf(entityPersonnelInfo.getPId().toString()), returnDto);

            //4、调用消费操作微服务2.4.7 abcChargeConfirm
            chargeBillRequest.getMessage().getInfo();
            String amount = requestMessage.getInfo().getPayBillAmt();
            String traceNo = requestMessage.getInfo().getTraceNo();
            Date payTime = DateUtil.str2Date(requestMessage.getInfo().getTransDate() + requestMessage.getInfo().getTransTime(), DateUtil.DEFAULT_FORMAT);
//            logger.info("======================调用abcChargeConfirm");
            abcChargeConfirm(entityPersonnelInfo.getComId(), Integer.valueOf(entityPersonnelInfo.getPId().toString()), traceNo, amount, payTime, entityXfAccountInfo.getAccountRechargeMoney(), entityXfAccountInfo.getAccountSubsidyMoney(), returnDto);
            logger.info("======================账单缴费成功");

        } catch (Exception e) {
            logger.info("======================账单缴费失败:" + e.getMessage());
            e.printStackTrace();
        } finally {

            respHead.setReturnCode(returnDto.getReturnCode());
            respHead.setReturnMessage(returnDto.getReturnMessage());
            respHead.setTransFlag("02");
            respHead.setTimeStamp(DateUtil.get(DateUtil.YYYYMMDDHHMMSSSSS));
            respHead.setChannel(chargeBillRequest.getMessage().getHead().getChannel());
            respHead.setTransCode(chargeBillRequest.getMessage().getHead().getTransCode());
            respHead.setTransSeqNum(chargeBillRequest.getMessage().getHead().getTransSeqNum());

            respInfo.setNumOpenMerchantOrder(chargeBillRequest.getMessage().getInfo().getNumOpenMerchantOrder());
            respInfo.setEpayCode(chargeBillRequest.getMessage().getInfo().getEpayCode());
            respInfo.setTraceNo(chargeBillRequest.getMessage().getInfo().getTraceNo());
            respInfo.setRefundFlag(returnDto.getRefundFlag());

            respMessage.setInfo(respInfo);
            respMessage.setHead(respHead);

            chargeBillResponse.setMessage(respMessage);
            responseJson = JSON.toJSONString(chargeBillResponse);

            //加签名
//            logger.info("======ChargeBillController============responseJson打印结果是（responseJson加密前）:" + responseJson);
            String signatrue = signatureAndVerification.signWhithsha1withrsa2(privateKeyString, responseJson);
            responseJson = signatrue + "||" + new String(Base64.encodeBase64(responseJson.getBytes("utf-8")));
            logger.info("======ChargeBillController============responseJson打印结果是（responseJson加密后）:" + responseJson);
            httpResponse.setCharacterEncoding("utf-8");
            httpResponse.setContentType("text/plain");
            httpResponse.getWriter().write(responseJson);
        }
    }

    @PostMapping(ExposeApiUrl.URL_ExposeApi_ABCconfirmTrace)
    public Result confirmTrace(@RequestBody ABCConfirmTraceRequest request) {
        logger.info("========缴费单笔流水查询接口==================================请求参数：" + request.toString());
        //返回代码
        ABCReturnDto returnDto = new ABCReturnDto("0000", "成功", "false");

        try {
            final String dockCode = "abcbridge";
            String privateKeyString = "";
            String publicKeyString = "";

            //1、调用单位微服务6.11获取单位平台对接列表getComDockList。
//            logger.info("========调用单位微服务6.11获取单位平台对接列表getComDockList==================================");
            CompanyDockListDto companyDockListDto = new CompanyDockListDto();
            companyDockListDto.setComId(request.getComId());
            Result comDockListResult = companyClientService.getComDockList(companyDockListDto);
            if (200 != comDockListResult.getCode()) {
                logger.info("========调用单位微服务6.11获取单位平台对接列表失败==================================");
                return ResultUtil.error(ResultEnum.Err_4115);
            }
            List<CompanyDockListVo> comdockList = JSON.parseArray(JSON.toJSONString(comDockListResult.getData()), CompanyDockListVo.class);
            Optional<CompanyDockListVo> companyDockList = comdockList.stream().filter(companyDockListVo -> dockCode.equals(companyDockListVo.getDockCode()) && StringUtils.isBlank(companyDockListVo.getServerCode())).findFirst();
            String merchantId = companyDockList.get().getComAppid();

            //2、调用单位微服务6.17读取通讯接口URL getDockApiUrl。
//            logger.info("========开始调用单位微服务6.17读取通讯接口URL==================================");
            GetDockApiUrlRequest getDockApiUrlRequest = new GetDockApiUrlRequest();
            getDockApiUrlRequest.setComId(request.getComId());
            getDockApiUrlRequest.setDockCode(dockCode);
            getDockApiUrlRequest.setGrade(0);
//            logger.info("========调用单位微服务6.17读取通讯接口URL getDockApiUrl================================== 参数：" + getDockApiUrlRequest.toString());
            Result getDockApiUrlResult = companyClientService.getDockApiUrl(getDockApiUrlRequest);

            if (200 != getDockApiUrlResult.getCode()) {
                logger.info("========读取通讯接口URL失败==================================");
                return ResultUtil.error(ResultEnum.Err_4116);
            }
            List<DockApiUrlVo> getDockApiUrlList = JSON.parseArray(JSON.toJSONString(getDockApiUrlResult.getData()), DockApiUrlVo.class);
            Optional<DockApiUrlVo> dockApiUrl = getDockApiUrlList.stream().findFirst();
            String reqUrl = dockApiUrl.get().getRequestUrl();

            if (StringUtils.isBlank(reqUrl)) {
                logger.info("========通讯接口URL为空==================================");
                return ResultUtil.error(ResultEnum.Err_4117);
            }
            //3、调用单位微服务6.21获取响应接口参数getReplyApiPara。
//            logger.info("========调用单位微服务6.21获取响应接口参数getReplyApiPara。==================================获取公钥");
            EntityComDockApi entityComDockApi = getReplyApiPara(merchantId, "abcbridge#confirmTrace", 1, returnDto);
            publicKeyString = entityComDockApi.getKey();

            //调用单位微服务6.21获取响应接口参数getReplyApiPara。
//            logger.info("========调用单位微服务6.21获取响应接口参数getReplyApiPara。==================================获取私钥");
            EntityComDockApi entityComDockApi2 = getReplyApiPara(merchantId, "abcbridge#confirmTrace", 4, returnDto);
            privateKeyString = entityComDockApi2.getKey();

            //输入项避免首尾出现空格的情况
            String traceNo = request.getChannelOrderNo().trim();
            merchantId = merchantId.trim();

            //创建发送请求对象
            String reqJson = getConfirmTraceRequest(merchantId, traceNo);
            //对需要发送的json字符串进行签名

            String signatrue = signatureAndVerification.signWhithsha1withrsa2(privateKeyString, reqJson);
//            logger.info("加密前发送的报文：" + reqJson);
            //加签名
            String reqStr = signatrue + "||" + Base64Util.encodeData(reqJson);
//            logger.info("发送的报文：" + reqStr);

            //发送签名信息获取返回签名信息
            String responseStr = HttpClientUtils.doPostStr(reqUrl, reqStr);
//            logger.info("接收到的报文：" + responseStr);

            if (responseStr.startsWith("{\"string\":")) {
                //如果系统发生异常则会返回"{"string":"异常信息"}"
                logger.info("异常信息-returnMessage", responseStr.substring(responseStr.indexOf(":") + 2, responseStr.indexOf("}") - 1));
                return ResultUtil.error(ResultEnum.Err_4118, responseStr.substring(responseStr.indexOf(":") + 2, responseStr.indexOf("}") - 1));
            } else {
                //截取签名信息
                String signature = responseStr.substring(0, responseStr.indexOf("||"));
//                logger.info("获取签名：" + signature);
                //截取加密的json信息，进行解密
                String requsetBody = responseStr.substring(responseStr.indexOf("||") + 2);
//                logger.info("获取请求：" + requsetBody);

                //验签
//                logger.info("========验签==================================");
                verifySign(publicKeyString, requsetBody, signature, request.getComId(), entityComDockApi.getComId().toString(), returnDto);

                //解密返回报文
                String respJson = Base64Util.decodeData(requsetBody);
                logger.info("获取签名解密后：" + respJson);

                //截取签名信息中的json字符串，并转化为对象
                ConfirmTraceResponse confirmTraceResponse = JSON.parseObject(respJson, new TypeReference<ConfirmTraceResponse>() {
                });

                ConfirmTraceResponse.Message.Head head = confirmTraceResponse.getMessage().getHead();
                ConfirmTraceResponse.Message.Info info = confirmTraceResponse.getMessage().getInfo();
                logger.info("head：【{}】", head);
                logger.info("info：【{}】", info);

                //如果返回2、4、5、99时调用消费操作微服务2.4.8 abcChargeFail
                if ("2|4|5|99".contains(info.getPayStatus())) {
//                    logger.info("========返回2、4、5、99时调用消费操作微服务2.4.8 abcChargeFail================================== traceNo：" + traceNo);
                    payHandleClientService.abcChargeFail(request.getComId(), "NHCZ" + traceNo);
                } else if ("1".equals(info.getPayStatus()) || "6".equals(info.getPayStatus())) {
//                    logger.info("========返回1时调用abcChargeConfirm==================================");
                    EntityXfAccountInfo entityXfAccountInfo = getXFAccount(request.getComId(), request.getPId(), returnDto);
                    abcChargeConfirm(request.getComId(), request.getPId(), traceNo, info.getAmtEpay(), DateUtil.str2Date(info.getTimeEpay(), DateUtil.DEFAULT_FORMAT), entityXfAccountInfo.getAccountRechargeMoney(), entityXfAccountInfo.getAccountSubsidyMoney(), returnDto);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.info("========缴费单笔流水查询接口失败==================================：" + e.getMessage() + "||" + returnDto.getReturnMessage());
            return ResultUtil.error(ResultEnum.Err_900, returnDto);
        }
//        logger.info("========缴费单笔流水查询接口结束==================================" + returnDto.toString());
        return ResultUtil.success(returnDto);
    }

    private String getConfirmTraceRequest(String merchantId, String traceNo) {
        ConfirmTraceRequest confirmTraceRequest = new ConfirmTraceRequest();
        //以当前时间为时间戳
        String stamp = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());

        //发送报文的格式，以json格式传送
        confirmTraceRequest.setFormat("json");
        // 交易的序列号需由第三方提供，且必须按照特定规则上送缴费中心，规则定义：BRIDGE前缀+当前17位时间戳timeStamp+商户号merchantId
        confirmTraceRequest.getMessage().getHead().setTransSeqNum("BRIDGE" + stamp + merchantId);
        //交易码，固定
        confirmTraceRequest.getMessage().getHead().setTransCode("confirmTrace");
        //时间戳格式 yyyyMMddHHmmssSSS，
        confirmTraceRequest.getMessage().getHead().setTimestamp(stamp);
        //上行下送标志，固定
        confirmTraceRequest.getMessage().getHead().setTransFlag("01");

        //缴费项目配置的主商户在商E付系统的编号
        confirmTraceRequest.getMessage().getInfo().setMerchantId(merchantId);
        //标志唯一一笔流水，可以用来查日志，必须跟缴费账单流水和查询账单流水保持一致
        confirmTraceRequest.getMessage().getInfo().setTraceNo(traceNo);

        //封装完成，将数据转为json格式，然后加密加签名
        String reqJson = JSON.toJSONString(confirmTraceRequest);
        return reqJson;
    }

    private EntityComDockApi getReplyApiPara(String merchantId, String dockApiCode, Integer keyType, ABCReturnDto returnDto) throws Exception {
        //1、	调用单位微服务6.21获取响应接口参数getReplyApiPara。
        GetReplyApiParaRequest getReplyApiParaRequest = new GetReplyApiParaRequest();
        getReplyApiParaRequest.setDockCode("abcbridge");
        getReplyApiParaRequest.setDockApiCode(dockApiCode);
        getReplyApiParaRequest.setSvrAppid("abcbridge");
        getReplyApiParaRequest.setComAppid(merchantId);
        getReplyApiParaRequest.setKeyType(keyType);

        Result getReplyApiParaResult = companyClientService.getReplyApiPara(getReplyApiParaRequest);
        if (getReplyApiParaResult.getCode() != 200) {
            returnDto.setReturnCode("JH03");
            returnDto.setReturnMessage("学校未开放权限");
            throw new Exception(returnDto.getReturnMessage());
        }
        return JSON.parseObject(JSON.toJSONString(getReplyApiParaResult.getData()), EntityComDockApi.class);
    }

    private void verifySign(String publicKeyString, String requsetBody, String signature, Long comId, String input1, ABCReturnDto returnDto) throws Exception {
        boolean flag = signatureAndVerification.read_RSA_and_verify_sign(publicKeyString, requsetBody, signature);
        if (!flag) {
            returnDto.setReturnCode("JH03");
            returnDto.setReturnMessage("验签失败");
            throw new Exception(returnDto.getReturnMessage());
        }

        if (StringUtils.isBlank(input1) || null == comId || !input1.equals(comId.toString())) {
            returnDto.setReturnCode("JH03");
            returnDto.setReturnMessage("学校与商户不匹配");
            throw new Exception(returnDto.getReturnMessage());
        }
        // 如果返回0，4，调用4.4.0.1验签：验签失败退出
        // 验签成功但接口参数返回4，返回JH03（ “学校未开放权限”）TODO
    }

    private UserInfoByNamePhoneVo getPinfoByNameCode(Long comId, String name, String pCode, ABCReturnDto returnDto) throws Exception {
        Result UserInfoByNamePhoneResult = humanFeignService.getPinfoByNameCode(comId, name, pCode);
        if (UserInfoByNamePhoneResult.getCode() != 200 || null == UserInfoByNamePhoneResult.getData()) {
            returnDto.setReturnCode("JH02");
            returnDto.setReturnMessage("用户不存在");
            returnDto.setRefundFlag("true");
            throw new Exception(returnDto.getReturnMessage());
        }
        return JSON.parseObject(JSON.toJSONString(UserInfoByNamePhoneResult.getData()), UserInfoByNamePhoneVo.class);

    }

    private EntityXfAccountInfo getXFAccount(Long comId, Integer pId, ABCReturnDto returnDto) throws Exception {
        Result xfAcount = payConfigClientService.GetXFAccount(comId, pId);
        if (xfAcount.getCode() != 200 || null == xfAcount.getData()) {
            returnDto.setReturnCode("JH06");
            returnDto.setReturnMessage("学生账户不存在");
            returnDto.setRefundFlag("true");
            throw new Exception(returnDto.getReturnMessage());
        }
        return JSON.parseObject(JSON.toJSONString(xfAcount.getData()), EntityXfAccountInfo.class);
    }

    private EntityXfRecordProcess abcCharge(EntityComDockApi entityComDockApi, UserInfoByNamePhoneVo entityPersonnelInfo, EntityXfAccountInfo entityXfAccountInfo, String traceNo, ABCReturnDto returnDto) throws Exception {
        EntityXfRecordProcess entityXfRecordProcess = new EntityXfRecordProcess();

        try {


            Date now = new Date();
            entityXfRecordProcess.setComId(entityPersonnelInfo.getComId());
            entityXfRecordProcess.setDeptId(entityPersonnelInfo.getDeptId());
            entityXfRecordProcess.setDeptName(entityPersonnelInfo.getDeptName());
            entityXfRecordProcess.setPId(entityPersonnelInfo.getPId());
            entityXfRecordProcess.setPCode(entityPersonnelInfo.getPCode());
            entityXfRecordProcess.setPName(entityPersonnelInfo.getPName());
            entityXfRecordProcess.setAccountNo(entityXfAccountInfo.getAccountNo());
            entityXfRecordProcess.setCardNo(getCardInfo(entityPersonnelInfo.getComId(), entityPersonnelInfo.getPId()));
            entityXfRecordProcess.setChargeBalance(entityXfAccountInfo.getAccountRechargeMoney());
            entityXfRecordProcess.setSubBalance(entityXfAccountInfo.getAccountSubsidyMoney());
            entityXfRecordProcess.setConsTime(now);
            entityXfRecordProcess.setConsMoney(0l);
            entityXfRecordProcess.setConsState(10);
            entityXfRecordProcess.setOpType(12l);
            entityXfRecordProcess.setOpTypeDiff(12l);
            entityXfRecordProcess.setOrderNo("NHCZ" + traceNo);
            entityXfRecordProcess.setPayTime(now);
            entityXfRecordProcess.setPayState(0);
            entityXfRecordProcess.setCreateTime(now);
            entityXfRecordProcess.setMonthValue(DateUtils.getStrDate(now, "yyyyMM"));
            entityXfRecordProcess.setChargeMoney(0l);
            entityXfRecordProcess.setRealMoney(0l);
            entityXfRecordProcess.setDeviceNo("abcbridge#queryBill");
            entityXfRecordProcess.setDeviceName("abcbridge");
            entityXfRecordProcess.setChannelOrderNo(traceNo);
            entityXfRecordProcess.setPayWay(1001);
            entityXfRecordProcess.setMealDate(new Date());
            entityXfRecordProcess.setMealNo("");

            payHandleClientService.InsertEntityXfRecord(entityXfRecordProcess);
        } catch (Exception e) {
            e.printStackTrace();
            returnDto.setReturnCode("JH12");
            returnDto.setReturnMessage("消费记录保存失败，请检查是否重复提交");
            throw new Exception(returnDto.getReturnMessage());
        }
        return entityXfRecordProcess;

    }

    private String getCardInfo(Long comId, Long pId){
        String cardNo = "";
        try {
            Result result = payConfigClientService.GetCardInfoByPid(comId, pId);
            if (200 == result.getCode() && null != result.getData()) {
                EntityCardInfo cardInfo = JSON.parseObject(JSON.toJSONString(result.getData()), EntityCardInfo.class);
                cardNo = cardInfo.getCardNo();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return cardNo;
    }

    private void abcChargeConfirm(Long comId, Integer pId, String traceNo, String amount, Date payTime, Long accountRrechargeMoney, Long accountSubsidyMoney, ABCReturnDto returnDto) throws Exception {
        ABCChargeConfirmVo vo = new ABCChargeConfirmVo();
        vo.setComId(comId);
        vo.setPId(pId);
        vo.setOrderNo("NHCZ" + traceNo);
        vo.setAmount(Long.valueOf(F2YAndY2FUtils.Y2F(amount)));
        vo.setPayTime(payTime);
        vo.setAccountRrechargeMoney(accountRrechargeMoney);
        vo.setAccountSubsidyMoney(accountSubsidyMoney);
        logger.info("======================abcChargeConfirm：参数 " + vo.toString());
        Result result = payHandleClientService.abcChargeConfirm(vo);
        logger.info("======================abcChargeConfirm：响应 " + result.getCode() + ":" + result.getMsg());
        if (null != result && null != result.getCode() && 200 != result.getCode()) {

            if (ResultEnum.Err_4101.getKey().equals(result.getCode())) {
                returnDto.setReturnCode("JH02");
                returnDto.setReturnMessage("充值账单不存在");
                returnDto.setRefundFlag("true");
                logger.info("======================abcChargeConfirm：异常 " + returnDto.getReturnMessage());
                throw new Exception(returnDto.getReturnMessage());
            } else {
                returnDto.setReturnCode("JH02");
                returnDto.setReturnMessage("账单异常");
                logger.info("======================abcChargeConfirm：异常 " + returnDto.getReturnMessage());
                throw new Exception(returnDto.getReturnMessage());
            }
        }
    }


    private void setRespBills(QueryBillResponse.Message.Info.Bill respBill, ArrayList<QueryBillResponse.Message.Info.Bill> respBills, String billNo, Long accountRechargeMoney) {
        respBill.setBillNo(billNo);
        respBill.setBillName("充值");
        respBill.setOweAmt(F2YAndY2FUtils.F2Y(String.valueOf(Math.min(Long.valueOf(accountRechargeMoney.toString()), 0l))));
        respBill.setFeeAmt("0.00");
        respBill.setMinAmt("0.01");
        respBill.setMaxAmt("500.00");
        respBill.setBalance(String.valueOf(F2YAndY2FUtils.F2Y(accountRechargeMoney.toString())));
        respBills.add(respBill);
    }

    private void setRespInfo(QueryBillRequest queryBillRequest, QueryBillResponse.Message.Info respInfo, String custName, String custAddress, ArrayList<QueryBillResponse.Message.Info.Bill> respBills) {
        respInfo.setEpayCode(queryBillRequest.getMessage().getInfo().getEpayCode());
        respInfo.setMerchantId(queryBillRequest.getMessage().getInfo().getMerchantId());
        respInfo.setTraceNo(queryBillRequest.getMessage().getInfo().getTraceNo());
        respInfo.setInput1(queryBillRequest.getMessage().getInfo().getInput1());
        respInfo.setCustName(custName);
        respInfo.setCustAddress(custAddress);
        respInfo.setAmtRule("3");
        respInfo.setTotalBillCount("1");
        respInfo.setBill(respBills);
    }

    private void setMessage(QueryBillResponse.Message.Head respHead, QueryBillResponse.Message.Info respInfo, QueryBillResponse.Message respMessage, QueryBillResponse response, ABCReturnDto returnDto) {
        respHead.setReturnCode(returnDto.getReturnCode());
        respHead.setReturnMessage(returnDto.getReturnMessage());
        respHead.setTransFlag("02");
        respHead.setTimeStamp(DateUtil.get(DateUtil.YYYYMMDDHHMMSSSSS));
        respMessage.setInfo(respInfo);
        respMessage.setHead(respHead);

        response.setMessage(respMessage);
    }

}
